package com.wtwd.device.controller;


import com.alibaba.fastjson.JSONObject;
import com.github.xiaoymin.knife4j.annotations.DynamicParameter;
import com.github.xiaoymin.knife4j.annotations.DynamicParameters;
import com.ruibty.nsfw.NsfwService;
import com.wtwd.device.constant.AuthCodeTypeEnum;
import com.wtwd.device.constant.RespCode;
import com.wtwd.device.constant.SeparatorConstant;
import com.wtwd.device.constant.UserStateEnum;
import com.wtwd.device.model.dto.TargetInfo;
import com.wtwd.device.model.entity.AppUser;
import com.wtwd.device.model.entity.AppUserInfo;
import com.wtwd.device.model.entity.AppUserTarget;
import com.wtwd.device.model.entity.Device;
import com.wtwd.device.model.vo.LoginVO;
import com.wtwd.device.model.vo.ResultVO;
import com.wtwd.device.model.vo.UploadFileVO;
import com.wtwd.device.service.*;
import com.wtwd.device.util.FileUtils;
import com.wtwd.device.util.StringUtil;
import com.wtwd.textsearch.TextSearchService;
import io.swagger.annotations.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author zdl
 * @since 2021-08-04
 */
@Api(tags = "用户信息管理")
@RestController
@RequestMapping("/app-user-info")
public class AppUserInfoController {

    @Resource
    private AppUserInfoService appUserInfoService;

    @Resource
    private AppUserService appUserService;

    @Resource
    private RedisService redisService;

    @Resource
    private AppUserTargetService appUserTargetService;

    @Resource
    private AppDeviceService appDeviceService;

    @Value("${file.path}")
    private String filePath;

    @Value("${app.portrait.folder}")
    private String appPortraitFolder;

    @Value("${file.http}")
    private String fileHttp;

    @Resource
    private TextSearchService textSearchService;


    @ApiOperation(value = "获取头像", notes = "图像为base64格式")
    @ApiResponses({@ApiResponse(code = 400, message = "参数错误")
    })
    @GetMapping("portrait")
    public ResultVO getPortrait() {
        Long currentUserId = appUserService.getCurrentUserId();
        AppUserInfo appUserInfo = appUserInfoService.getAppUserInfoByUserId(currentUserId);
        if (appUserInfo == null) {
            return ResultVO.success();
        }
        String portrait = appUserInfo.getPortrait();
        if (StringUtil.isEmpty(portrait)) {
            return ResultVO.success();
        }
        return ResultVO.success(FileUtils.getFileBase64(portrait));
    }


    @ApiOperation(value = "保存用户信息", notes = "第一次保存时,需提交所有参数")
    @ApiResponses({@ApiResponse(code = 400, message = "参数错误")
    })
    @Transactional
    @PostMapping("/userInfo")
    public ResultVO saveUserInfo(@RequestBody AppUserInfo userInfoModel) {
        boolean isSuccess;
        String name = userInfoModel.getName();
        if (checkNameNSFW(name)) {
            name = "该昵称包含敏感词汇";
        }
        Long userId = appUserService.getCurrentUserId();
        AppUserInfo appUserInfoByUserId = appUserInfoService.getAppUserInfoByUserId(userId);
        userInfoModel.setUserId(userId);
        userInfoModel.setCreateTime(null);
        userInfoModel.setUpdateTime(null);
        userInfoModel.setName(name);

        if (appUserInfoByUserId == null) {
            isSuccess = appUserInfoService.save(userInfoModel);
        } else {
            isSuccess = appUserInfoService.update(userInfoModel);
        }
        if (userInfoModel.getTargetSteps() != null && isSuccess) {
            AppUserTarget userTarget = new AppUserTarget();
            userTarget.setUserId(userId);
            userTarget.setStepNumber(userInfoModel.getTargetSteps());
            isSuccess = appUserTargetService.save(userTarget);
        }
        return isSuccess ? ResultVO.success() : ResultVO.error(RespCode.FAIL);
    }

    private boolean checkNameNSFW(String name) {
        return StringUtil.isNotEmpty(name) && textSearchService.isMatch(name);
    }

    @ApiOperation(value = "获取用户信息")
    @ApiResponses({@ApiResponse(code = 400, message = "参数错误")
    })
    @GetMapping("/userInfo")
    public ResultVO<AppUserInfo> getUserInfo() {
        Long currentUserId = appUserService.getCurrentUserId();
        AppUserInfo appUserInfo = appUserInfoService.getAppUserInfoByUserId(currentUserId);
        if (appUserInfo == null) {
            appUserInfo = appUserService.getDefaultObj(currentUserId);
        } else {
            AppUserTarget target = appUserTargetService.getByUserId(currentUserId);
            if (target != null) {
                appUserInfo.setTargetSteps(target.getStepNumber());
            } else {
                appUserInfo.setTargetSteps(new AppUserTarget().getDefaultObj(currentUserId).getStepNumber());
            }
        }
        return ResultVO.success(appUserInfo);
    }

    @ApiOperation(value = "修改密码", notes = "")
    @DynamicParameters(name = "passwordModel", properties = {
            @DynamicParameter(name = "password", value = "新密码", dataTypeClass = String.class, required = true),
    })
    @ApiResponses({
            @ApiResponse(code = 400, message = "参数错误")
            , @ApiResponse(code = 1007, message = "密码格式错误")
    })
    @PostMapping("/changePassword")
    public ResultVO<LoginVO> changePassword(@RequestBody JSONObject passwordModel) {
        String password = passwordModel.getString("password");
        if (StringUtils.isBlank(password)) {
            return ResultVO.error(RespCode.PASSWORD_FORMAT_ERROR);
        }
        AppUser appUser = new AppUser();
        appUser.setUserId(appUserService.getCurrentUserId());
        appUser.setPassword(password);
        if (appUserService.updateById(appUser)) {
            return ResultVO.success();
        }
        return ResultVO.error(RespCode.FAIL);
    }

    @ApiOperation(value = "修改手机号", notes = "")
    @DynamicParameters(name = "changePhoneModel", properties = {
            @DynamicParameter(name = "phone", value = "新手机号", dataTypeClass = String.class, required = true)
            , @DynamicParameter(name = "areaCode", value = "区号", dataTypeClass = String.class, required = true)
            , @DynamicParameter(name = "authCode", value = "验证码", dataTypeClass = String.class, required = true)
    })
    @ApiResponses({
            @ApiResponse(code = 400, message = "参数错误")
            , @ApiResponse(code = 1001, message = "验证码错误")
            , @ApiResponse(code = 1002, message = "手机格式错误")
            , @ApiResponse(code = 1003, message = "手机已存在")
    })
    @PostMapping("/changePhone")
    public ResultVO<LoginVO> changePhone(@RequestBody JSONObject passwordModel) {
        String phone = passwordModel.getString("phone");
        String areaCode = passwordModel.getString("areaCode");
        String authCode = passwordModel.getString("authCode");
        if (StringUtils.isAnyBlank(phone, areaCode, authCode)) {
            return ResultVO.error(RespCode.PARAMS_ERROR);
        }
        if (StringUtil.isNotNumber(phone)) {
            return ResultVO.error(RespCode.PHONE_FORMAT_ERROR);
        }
        if (!redisService.verifyCode(phone, AuthCodeTypeEnum.MODIFY_ACCOUNT.getType(), authCode)) {
            return ResultVO.error(RespCode.AUTH_CODE_ERROR);
        }
        AppUser appUser = new AppUser();
        appUser.setUserId(appUserService.getCurrentUserId());
        appUser.setPhone(phone);
        appUser.setAreaCode(areaCode);
        try {
            appUserService.updateById(appUser);
        } catch (DuplicateKeyException e) {
            return ResultVO.error(RespCode.PHONE_EXIST);
        }
        return ResultVO.success();
    }

    @ApiOperation(value = "修改邮箱", notes = "")
    @DynamicParameters(name = "changeEmailModel", properties = {
            @DynamicParameter(name = "email", value = "新手机号", dataTypeClass = String.class, required = true)
            , @DynamicParameter(name = "authCode", value = "验证码", dataTypeClass = String.class, required = true)
    })
    @ApiResponses({
            @ApiResponse(code = 400, message = "参数错误")
            , @ApiResponse(code = 1001, message = "验证码错误")
            , @ApiResponse(code = 1009, message = "邮箱格式错误")
            , @ApiResponse(code = 1004, message = "邮箱已存在")
    })
    @PostMapping("/changeEmail")
    public ResultVO<LoginVO> changeEmail(@RequestBody JSONObject changeEmailModel) {
        String email = changeEmailModel.getString("email");
        String authCode = changeEmailModel.getString("authCode");
        if (StringUtils.isAnyBlank(email, authCode)) {
            return ResultVO.error(RespCode.PARAMS_ERROR);
        }
        if (StringUtil.isNotEmail(email)) {
            return ResultVO.error(RespCode.EMAIL_FORMAT_ERROR);
        }
        if (!redisService.verifyCode(email, AuthCodeTypeEnum.MODIFY_ACCOUNT.getType(), authCode)) {
            return ResultVO.error(RespCode.AUTH_CODE_ERROR);
        }
        AppUser appUser = new AppUser();
        appUser.setUserId(appUserService.getCurrentUserId());
        appUser.setEmail(email);
        try {
            appUserService.updateById(appUser);
        } catch (DuplicateKeyException e) {
            return ResultVO.error(RespCode.EMAIL_EXIST);
        }
        return ResultVO.success();
    }


    @Resource
    private NsfwService nsfwService;

    @ApiOperation(value = "上传头像", notes = "上传头像后,返回头像访问路径,建议图片大小不超100K")
    @ApiImplicitParam(name = "file", value = "头像文件", required = true, dataTypeClass = MultipartFile.class)
    @ApiResponses({@ApiResponse(code = 400, message = "参数错误")
    })
    @PostMapping("/uploadPortrait")
    public ResultVO<UploadFileVO> uploadPortrait(@RequestBody MultipartFile file) {
        String originalFilename = file.getOriginalFilename();
        String newFileName = String.valueOf(appUserService.getCurrentUserId());
        boolean isNSFW = false;
        try {
            isNSFW = nsfwService.getPrediction(file.getBytes()) > 0.8;
        } catch (IOException e) {
            e.printStackTrace();
        }
        String uploadPath;
        if (isNSFW) {
            newFileName = newFileName + "NSFW";
        }
        try {
            uploadPath = FileUtils.uploadImg(filePath.concat(appPortraitFolder), newFileName, originalFilename, file.getInputStream());
        } catch (IOException e) {
            return ResultVO.error();
        }
        if (uploadPath == null) {
            return ResultVO.error();
        }
        UploadFileVO uploadFileVO = new UploadFileVO();
        uploadFileVO.setFileUrl(fileHttp.concat(appPortraitFolder).concat(uploadPath.substring(uploadPath.lastIndexOf(SeparatorConstant.DELIMITER) + 1)));
        if (isNSFW) {
            uploadFileVO.setFileUrl(fileHttp.concat("/NSFW.png"));
        }
        return ResultVO.success(uploadFileVO);
    }

    @ApiOperation(value = "保存用户目标", notes = "第一次保存时,需提交所有参数")
    @ApiResponses({
            @ApiResponse(code = 400, message = "参数错误")
    })
    @PostMapping("/userTarget")
    public ResultVO saveUserTarget(@RequestBody TargetInfo targetModel) {
        AppUserTarget target = targetModel.toEntity();
        target.setUserId(appUserService.getCurrentUserId());
        if (appUserTargetService.save(target)) {
            return ResultVO.success();
        }
        return ResultVO.error(RespCode.FAIL);
    }

    @ApiOperation(value = "获取用户目标", notes = "")
    @ApiResponses({
            @ApiResponse(code = 400, message = "参数错误")
    })
    @GetMapping("/userTarget")
    public ResultVO<TargetInfo> getUserTarget() {
        Long currentUserId = appUserService.getCurrentUserId();
        AppUserTarget userTarget = appUserTargetService.getByUserId(currentUserId);
        userTarget = userTarget == null ? new AppUserTarget().getDefaultObj(currentUserId) : userTarget;
        return ResultVO.success(TargetInfo.toThis(userTarget));
    }

    @ApiOperation("绑定邮箱")
    @DynamicParameters(name = "emailBindModel", properties = {
            @DynamicParameter(name = "email", value = "手机号", dataTypeClass = String.class, required = true)
            , @DynamicParameter(name = "code", value = "验证码", dataTypeClass = String.class, required = true)
            , @DynamicParameter(name = "password", value = "登录密码", dataTypeClass = String.class, required = true)
    })
    @ApiResponses({@ApiResponse(code = 400, message = "参数错误")
            , @ApiResponse(code = 1001, message = "验证码错误")
            , @ApiResponse(code = 1009, message = "邮箱格式有误")
    })
    @PostMapping("/bindUserByEmail")
    public ResultVO bindUserByEmail(@RequestBody JSONObject emailBindModel) {
        String email = emailBindModel.getString("email");
        String password = emailBindModel.getString("password");
        String code = emailBindModel.getString("code");
        if (StringUtils.isAnyBlank(email, password, code)) {
            return ResultVO.error(RespCode.PARAMS_ERROR);
        }
        if (StringUtil.isNotEmail(email)) {
            return ResultVO.error(RespCode.EMAIL_FORMAT_ERROR);
        }
        if (!redisService.verifyCode(email, AuthCodeTypeEnum.REGISTER.getType(), code)) {
            return ResultVO.error(RespCode.AUTH_CODE_ERROR);
        }
        Long currentUserId = appUserService.getCurrentUserId();
        AppUser appUser = new AppUser();
        appUser.setUserId(currentUserId);
        appUser.setEmail(email);
        appUser.setPassword(password);
        try {
            if (!appUserService.save(appUser)) {
                return ResultVO.error(RespCode.FAIL);
            }
        } catch (DuplicateKeyException e) {
            return ResultVO.error(RespCode.EMAIL_EXIST);
        }
        return ResultVO.success();
    }

    @ApiOperation("绑定手机")
    @DynamicParameters(name = "phoneBindModel", properties = {
            @DynamicParameter(name = "phone", value = "手机号", dataTypeClass = String.class, required = true)
            , @DynamicParameter(name = "code", value = "验证码", dataTypeClass = String.class, required = true)
            , @DynamicParameter(name = "area", value = "区域", dataTypeClass = String.class, required = true)
            , @DynamicParameter(name = "areaCode", value = "手机区号", dataTypeClass = String.class, required = true, example = "86,不包含+号")
            , @DynamicParameter(name = "password", value = "登录密码", dataTypeClass = String.class, required = true)
    })
    @ApiResponses({@ApiResponse(code = 400, message = "参数错误")
            , @ApiResponse(code = 1001, message = "验证码错误")
            , @ApiResponse(code = 1002, message = "手机格式错误")
            , @ApiResponse(code = 1003, message = "手机号已存在")
    })
    @PostMapping("/bindUserByPhone")
    public ResultVO bindUserByPhone(@RequestBody JSONObject phoneBindModel) {
        String phone = phoneBindModel.getString("phone");
        String code = phoneBindModel.getString("code");
        String area = phoneBindModel.getString("area");
        String areaCode = phoneBindModel.getString("areaCode");
        String password = phoneBindModel.getString("password");
        if (StringUtils.isAnyBlank(phone, code, area, areaCode, password)) {
            return ResultVO.error(RespCode.PARAMS_ERROR);
        }
        if (StringUtil.isNotNumber(phone)) {
            return ResultVO.error(RespCode.PHONE_FORMAT_ERROR);
        }
        if (!redisService.verifyCode(phone, AuthCodeTypeEnum.REGISTER.getType(), code)) {
            return ResultVO.error(RespCode.AUTH_CODE_ERROR);
        }
        Long currentUserId = appUserService.getCurrentUserId();
        AppUser appUser = new AppUser();
        appUser.setUserId(currentUserId);
        appUser.setPhone(phone);
        appUser.setAreaCode(areaCode);
        appUser.setArea(area);
        appUser.setPassword(password);
        try {
            if (!appUserService.save(appUser)) {
                return ResultVO.error(RespCode.FAIL);
            }
        } catch (DuplicateKeyException e) {
            return ResultVO.error(RespCode.PHONE_EXIST);
        }
        return ResultVO.success();
    }

    /**
     * 1.校验身份
     * 2.注销用户
     * 3.解绑所有设备,并且清除设备信息
     * 4.清除用户数据
     *
     * @param logoutUserModel
     * @return
     */
    @ApiOperation(value = "注销用户", notes = "解绑所有设备,并且清除设备信息,及用户信息")
    @DynamicParameters(name = "logoutUserModel", properties = {
            @DynamicParameter(name = "password", value = "登录密码", dataTypeClass = String.class, required = true)
    })
    @ApiResponses({@ApiResponse(code = 400, message = "参数错误")
    })
    @PostMapping("/logoutUser")
    public ResultVO logoutUser(@RequestBody JSONObject logoutUserModel) {
        String password = logoutUserModel.getString("password");
        Long currentUserId = appUserService.getCurrentUserId();
        AppUser user = appUserService.getUserByUserId(currentUserId);
        if (user.getPassword() != null && !user.getPassword().equals(password)) {
            return ResultVO.error(RespCode.ACCOUNT_PASSWORD_ERROR);

        }
        AppUserInfo userInfo = appUserService.getDefaultObj(currentUserId);
        userInfo.setPortrait("");
        userInfo.setState(UserStateEnum.Logout.getCode());
        appUserInfoService.update(userInfo);
        Device device = appDeviceService.getDeviceByUserId(currentUserId);
        if (device != null) {
            appDeviceService.unbindDeviceAndClearUserInfo(currentUserId, device.getMacAddress());
        }
        appUserService.deleteById(currentUserId);
        appUserService.clearUserData(currentUserId);
        return ResultVO.success();
    }

    /**
     * 1.校验身份
     * 2.清除用户数据
     *
     * @param clearUserModel
     * @return
     */
    @ApiOperation("清除用户数据")
    @DynamicParameters(name = "clearUserModel", properties = {
            @DynamicParameter(name = "password", value = "登录密码", dataTypeClass = String.class, required = true)
    })
    @ApiResponses({@ApiResponse(code = 400, message = "参数错误")
    })
    @PostMapping("/clearUserInfo")
    public ResultVO clearUserInfo(@RequestBody JSONObject clearUserModel) {
        String password = clearUserModel.getString("password");
        Long currentUserId = appUserService.getCurrentUserId();
        AppUser user = appUserService.getUserByUserId(currentUserId);
        if (user.getPassword() != null && !user.getPassword().equals(password)) {
            return ResultVO.error(RespCode.ACCOUNT_PASSWORD_ERROR);
        }
        AppUserInfo userInfo = appUserService.getDefaultObj(currentUserId);
        userInfo.setPortrait("");
        appUserInfoService.update(userInfo);
        appUserService.clearUserData(currentUserId);
        return ResultVO.success();
    }

    @ApiOperation(value = "设置用户语言", notes = "该接口,建议每次启动应用后调用")
    @DynamicParameters(name = "setlanguageModel", properties = {
            @DynamicParameter(name = "language", value = "语言代码,详情见《国际化文档》", dataTypeClass = String.class, required = true)
    })
    @ApiResponses({@ApiResponse(code = 400, message = "参数错误")
    })
    @PostMapping("setLanguage")
    public ResultVO setUserLanguage(@RequestBody JSONObject setlanguageModel) {
        String language = setlanguageModel.getString("language");
        if (StringUtils.isBlank(language)) {
            return ResultVO.error(RespCode.PARAMS_ERROR);
        }
        Long currentUserId = appUserService.getCurrentUserId();
        AppUserInfo userInfo = new AppUserInfo();
        userInfo.setLang(language);
        userInfo.setUserId(currentUserId);
        return appUserInfoService.update(userInfo) ? ResultVO.success() : ResultVO.error();
    }


}

